///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@
//
// Στο παρόν περιγράφουμε μεθόδους που αφορούν μόνο στον server σκηνικού (skiser).
// Τέτοιες μέθοδοι είναι, π.χ. η επανασύσταση του σκηνικού από τα στοιχεία τής
// database, το κλείδωμα ενός τραπεζιού, το μοίρασμα μιας νέας διανομής κλπ.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

// Ακολουθεί μέθοδος με την οποία στήνεται ένα σκηνικό, ή καλύτερα ΤΟ σκηνικό στον
// skiser. Η μέθοδος αποτελεί ουσιαστικά το σημείο εκκίνησης της διαδικασίας, καθώς
// υπάρχει πληθώρα επιμέρους διαδικασιών που καλούνται αλυσιδωτά προκειμένου να
// στηθεί το σκηνικό. Περιττό να πούμε ότι το στήσιμο του σκηνικού στον skiser
// γίνεται με βάση τα στοιχεία που υπάρχουν κρατημένα στην database, και λαμβάνει
// χώρα κατά το ανέβασμα του skiser.  

Skiniko.prototype.stisimo = function() {
	Log.fasi.nea('Στήσιμο και ανασύσταση σκηνικού');
	this.stisimoKafenio(DB.connection());
	return this;
};

// Διαβάζουμε τα καφενεία από την database και τα εντάσσουμε στο σκηνικό.

Skiniko.prototype.stisimoKafenio = function(conn) {
	var query;

	Log.print('καφενεία');
	this.kafenio = {};
	query = 'SELECT ' + Kafenio.projection + ' FROM `kafenio`';
	conn.query(query, function(conn, rows) {
		Globals.awalk(rows, function(i, kafenio) {
			var prive;

			kafenio.prive = (kafenio['idiotikotita'] === 'ΠΡΙΒΕ');
			delete kafenio['idiotikotita'];

			skiniko.skinikoKafenioSet(new Kafenio(kafenio));
		});

		skiniko.stisimoDiapiste(conn);
	});

	return this;
};

// Διαβάζουμε τα διαπιστευτήρια των παικτών στα διάφορα καφενεία.

Skiniko.prototype.stisimoDiapiste = function(conn) {
	var query;

	Log.print('διαπιστευτήρια');
	query = 'SELECT ' + Diapiste.projection + ' FROM `diapiste`';
	conn.query(query, function(conn, rows) {
		Globals.awalk(rows, function(i, diapiste) {
			skiniko.skinikoDiapisteSet(new Diapiste(diapiste));
		});

		Log.level.push();
		skiniko.stisimoTrapezi(conn);
	});

	return this;
};

// Διαβάζουμε τα τραπέζια από την database και τα εντάσσουμε στο σκηνικό.

Skiniko.prototype.stisimoTrapezi = function(conn) {
	var query;

	Log.print('τραπέζια');
	query = 'SELECT ' + Trapezi.projection + ' FROM `trapezi`';
	conn.query(query, function(conn, rows) {
		Globals.awalk(rows, function(i, trapezi) {
			skiniko.skinikoTrapeziSet(new Trapezi(trapezi));
		});

		Log.level.push();
		skiniko.stisimoTrparam(conn);
	});

	return this;
};

// Διαβάζουμε τις παραμέτρους τραπεζιών από την database και τις εντάσσουμε στο σκηνικό.

Skiniko.prototype.stisimoTrparam = function(conn) {
	var query;

	Log.print('παράμετροι');
	query = 'SELECT ' + Trparam.projection + ' FROM `trparam`';
	conn.query(query, function(conn, rows) {
		Globals.awalk(rows, function(i, trparam) {
			skiniko.
			skinikoTrapeziGet(trparam['trapezi']).
			trapeziTrparamSet(trparam['param'], trparam['timi']);
		});

		skiniko.stisimoSinthesi(conn);
	});

	return this;
};

Skiniko.prototype.stisimoSinthesi = function(conn) {
	var query;

	Log.print('συνθέσεις');
	query = 'SELECT ' + Sinthesi.projection + ' FROM `sinthesi` WHERE `exodos` IS NULL';
	conn.query(query, function(conn, rows) {
		Globals.awalk(rows, function(i, sinthesi) {
			skiniko.
			skinikoTrapeziGet(sinthesi['trapezi']).
			trapeziPektisSet(sinthesi['thesi'], sinthesi['pektis']).
			trapeziApodoxiSet(sinthesi['thesi'], sinthesi['apodoxi']);
		});

		Log.level.pop();
		skiniko.stisimoSinedria(conn);
	});

	return this;
};

Skiniko.prototype.stisimoSinedria = function(conn) {
	var query;

	Log.print('συνεδρίες');
	query = 'SELECT ' + Sinedria.projection + ' FROM `sinedria`';
	conn.query(query, function(conn, rows) {
		Globals.awalk(rows, function(i, sinedria) {
			skiniko.skinikoSinedriaSet(new Sinedria(sinedria));
		});

		skiniko.stisimoPektis(conn);
	});

	return this;
};

// Έχουμε ήδη ανεβάσει στο σκηνικό καφενεία, τραπέζια και συνεδρίες και ήρθε η ώρα
// να ανεβάσουμε στοιχεία για τους παίκτες που εμπλέκονται σε όλα τα παραπάνω.

Skiniko.prototype.stisimoPektis = function(conn) {
	var pektisList = {};

	Log.print('παίκτες');

	this.skinikoSinedriaWalk(function() {
		pektisList[this.sinedriaPektisGet()] = true;
	});

	this.skinikoTrapeziWalk(function() {
		this.trapeziThesiWalk(function(thesi) {
			pektisList[this.trapeziPektisGet(thesi)] = true;
		});
	});

	this.skinikoKafenioWalk(function() {
		pektisList[this.kafenioDimiourgosGet()] = true;
	});

	delete pektisList[undefined];
	skiniko.stisimoPektisData(conn, pektisList);

	return this;
};

Skiniko.prototype.stisimoPektisData = function(conn, plist) {
	var login;

	for (login in plist) {
		this.pektisFreskarisma(login, {
			dbconn: conn,
			callback: function(conn) {
				delete plist[login];
				skiniko.stisimoPektisData(conn, plist);
			},
		});

		return this;
	}

	skiniko.stisimoTelos(conn);
	return this;
};

// Ακολουθεί η τελευταία μέθοδος που καλείται κατά το στήσιμο του σκηνικού.

Skiniko.prototype.stisimoTelos = function(conn) {
	conn.free();

	// Κάνουμε replay όλες τις παρτίδες με βάση τα στοιχεία που έχουμε
	// ήδη φορτώσει.

	Log.print('replay παρτίδων');
	this.skinikoTrapeziWalk(function() {
		this.partidaReplay();
	});

	// Αρχειοθετούμε τυχόν παλαιές συνεδρίες.

	Service.sinedria.check();

	// Ετοιμάζουμε το transaction log, ήτοι ένα array κινήσεων μέσω των
	// οποίων γίνονται αλλαγές στο σκηνικό.

	this.kinisi = [];

	// Εκκινούμε τον skiser ως server εξυπηρέτησης αιτημάτων σκηνικού.
	// Αυτά τα αιτήματα είναι είτε αιτήματα που αφορούν στην ενημέρωση
	// του σκηνικού των clients, είτε αιτήματα αλλαγής σκηνικού (κινήσεις).

	Server.ekinisi(this);
	return this;
};

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

// Η μέθοδος "pektisFreskarisma" δέχεται ένα login name και επιχειρεί να ανανεώσει
// τα στοιχεία του φερώνυμου παίκτη από τα στοιχεία της database. Ως δεύτερη παράμετρο
// μπορούμε να περάσουμε μια σειρά από options:
//
//	dbconn		Σύνδεση με την database στα πλαίσια της οποίας θα εκτελεστούν
//			τα απαραίτητα queries. Αν δεν έχει καθοριστεί, δημιουργείται
//			νέα σύνδεση με την database.
//
//	callback	Function που καλείται μετά το πέρας των εργασιών. Η function
//			καλείται ως μέθοδος του σκηνικού με παράμετρο τη σύνδεση με
//			την database. Αν δεν καθοριστεί callback function, τότε
//			καλείται function η οποία κλείνει τη σχετική σύνδεση με την
//			database.

Skiniko.prototype.pektisFreskarisma = function(login, opts) {
	var skiniko = this, query;

	if (opts === undefined)
	opts = {};

	if (!opts.hasOwnProperty('dbconn'))
	opts.dbconn = DB.connection();

	if (!opts.hasOwnProperty('callback'))
	opts.callback = function(conn) {
		conn.free();
	};

	query = 'SELECT ' + Pektis.projection + ' FROM `pektis` WHERE `login` LIKE ' + login.json();
	opts.dbconn.query(query, function(conn, rows) {
		// Αν βρέθηκε γραμμή με τα στοιχεία του αναζητούμενου παίκτη,
		// προχωρούμε στις επόμενες φάσεις αλυσιδωτά εκκινώντας με τις
		// παραμέτρους του παίκτη.

		if (rows.length) {
			skiniko.pektisFreskarismaPeparam(new Pektis(rows[0]), opts);
			return;
		}

		// Ο παίκτης δεν βρέθηκε στην database, επομένως τον καταργούμε
		// και από το σκηνικό.

		skiniko.skinikoPektisDelete(login);

		// Η διαδικασία έχει τελειώσει, επομένως καλούμε την callback function
		// ως μέθοδο του σκηνικού, με παράμετρο τη σύνδεση με την database.

		opts.callback.call(skiniko, conn);
		console.error(login + ': δεν βρέθηκε ο παίκτης στην database');
	});

	return this;
};

Skiniko.prototype.pektisFreskarismaPeparam = function(pektis, opts) {
	var skiniko = this, query;

	query = 'SELECT ' + Peparam.projection + ' FROM `peparam` WHERE `pektis` LIKE ' + pektis.pektisLoginGet().json();
	opts.dbconn.query(query, function(conn, rows) {
		Globals.awalk(rows, function(i, peparam) {
			pektis.pektisPeparamSet(peparam['param'], peparam['timi']);
		});

		skiniko.pektisFreskarismaProfinfo(pektis, opts);
	});

	return this;
};

Skiniko.prototype.pektisFreskarismaProfinfo = function(pektis, opts) {
	var skiniko = this, query;

	query = 'SELECT ' + Profinfo.projection + ' FROM `profinfo` WHERE `pektis` LIKE ' + pektis.pektisLoginGet().json();
	opts.dbconn.query(query, function(conn, rows) {
		Globals.awalk(rows, function(i, profinfo) {
			pektis.pektisProfinfoSet(profinfo['sxoliastis'], profinfo['kimeno']);
		});

		skiniko.pektisFreskarismaSxesi(pektis, opts);
	});

	return this;
};

Skiniko.prototype.pektisFreskarismaSxesi = function(pektis, opts) {
	var skiniko = this, query;

	query = 'SELECT ' + Sxesi.projection + ' FROM `sxesi` WHERE `pektis` LIKE ' + pektis.pektisLoginGet().json();
	opts.dbconn.query(query, function(conn, rows) {
		Globals.awalk(rows, function(i, sxesi) {
			pektis.pektisSxesiSet(sxesi['sxetizomenos'], sxesi['sxesi']);
		});

		skiniko.skinikoPektisSet(pektis);
		opts.callback.call(skiniko, conn);
	});

	return this;
};

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

Sinedria.prototype.sinedriaKlidiSet = function(klidi) {
	this.klidi = klidi;
	return this;
};

Sinedria.prototype.sinedriaKlidiGet = function() {
	return this.klidi;
};

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////@

// Ακολουθούν projection lists των πεδίων των πινάκων που διαβάζουμε από την
// database για την επανακατασκευή του σκηνικού.

Kafenio.projection =
	'`kodikos`, ' +
	'`onomasia`, ' +
	'`dimiourgos`, ' +
	'UNIX_TIMESTAMP(`enarxi`) AS `stisimo`, ' +
	'`idiotikotita`';

Diapiste.projection =
	'`kafenio`, ' +
	'`pektis`, ' +
	'UNIX_TIMESTAMP(`epidosi`) AS `epidosi`';

Trapezi.projection =
	'`kodikos`, ' +
	'`kafenio`, ' +
	'UNIX_TIMESTAMP(`stisimo`) AS `stisimo`, ' +
	'UNIX_TIMESTAMP(`poll`) AS `poll`, ' +
	'UNIX_TIMESTAMP(`arxio`) AS `arxio`';

Trparam.projection =
	'`param`, ' +
	'`timi`';

Sinthesi.projection =
	'`trapezi`, ' +
	'`thesi`, ' +
	'`pektis`, ' +
	'`apodoxi`, ' +
	'`exodos`';

Simetoxi.projection =
	'`trapezi`, ' +
	'`pektis`, ' +
	'`thesi`';

Dianomi.projection =
	'`kodikos`, ' +
	'`trapezi`, ' +
	'UNIX_TIMESTAMP(`enarxi`) AS `enarxi`, ' +
	'`dealer`, ' +
	'`kasa1`, `metrita1`, ' +
	'`kasa2`, `metrita2`, ' +
	'`kasa3`, `metrita3`, ' +
	'UNIX_TIMESTAMP(`telos`) AS `telos`';

Energia.projection =
	'`kodikos`, ' +
	'`dianomi`, ' +
	'`pektis`, ' +
	'`idos`, ' +
	'`data`, ' +
	'UNIX_TIMESTAMP(`pote`) AS `pote`';

Sizitisi.projection =
	'`kodikos`, ' +
	'`pektis`, ' +
	'`kafenio`, ' +
	'`trapezi`, ' +
	'`kimeno`, ' +
	'UNIX_TIMESTAMP(`pote`) AS `pote`';

Sinedria.projection =
	'`pektis`, ' +
	'`klidi`, ' +
	'`ip`, ' +
	'UNIX_TIMESTAMP(`isodos`) AS `isodos`, ' +
	'`kafenio`, `trapezi`, `thesi`, `simetoxi`';

Pektis.projection =
	'`login`, ' +
	'UNIX_TIMESTAMP(`egrafi`) AS `egrafi`, ' +
	'`onoma`, ' +
	'`email`';

Peparam.projection =
	'`param`, ' +
	'`timi`';

Sxesi.projection =
	'`sxetizomenos`, ' +
	'`sxesi`';

Profinfo.projection =
	'`sxoliastis`, ' +
	'`kimeno`';

Prosklisi.projection =
	'`trapezi`, ' +
	'`apo`, ' +
	'`pros`, ' +
	'UNIX_TIMESTAMP(`epidosi`) AS `epidosi`';
